-
Notifications
You must be signed in to change notification settings - Fork 13.3k
introduce dirty list to dataflow #51900
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This comment has been minimized.
This comment has been minimized.
src/librustc_mir/dataflow/mod.rs
Outdated
builder.propagate_bits_into_graph_successors_of( | ||
in_out, &mut self.changed, (mir::BasicBlock::new(bb_idx), bb_data)); | ||
while let Some(bb) = dirty_queue.pop() { | ||
let bb_data: &BasicBlockData<'tcx> = &mir.basic_blocks()[*bb]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
easier: &mir[bb]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, no type annotation is needed here (but it doens't hurt)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done!
src/librustc_mir/dataflow/mod.rs
Outdated
in_out, &mut self.changed, (mir::BasicBlock::new(bb_idx), bb_data)); | ||
while let Some(bb) = dirty_queue.pop() { | ||
let bb_data: &BasicBlockData<'tcx> = &mir.basic_blocks()[*bb]; | ||
let builder = &mut self.builder; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
odd indentation; and why introduce let
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed indentation, let
is introduced in diff because of bad indentation. Anyway, I have removed the dependency of that builder
variable.
src/librustc_mir/dataflow/mod.rs
Outdated
{ | ||
let sets = builder.flow_state.sets.for_block(bb_idx); | ||
debug_assert!(in_out.words().len() == sets.on_entry.words().len()); | ||
in_out.clone_from(sets.on_entry); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nnethercote noticed that this name (clone_from
) was causing problems (it shadows clone_from
from the Clone
trait, and sometimes that gets called instead, which is less efficient). They have a PR to fix it, but in the meantime, do this, which will ensure we're calling the method we want:
IdxSet::clone_from(in_out, sets.on_entry);
that said, I think we will be calling the correct one here anyway, given the type of in_out
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done!
src/librustc_mir/dataflow/mod.rs
Outdated
in_out.subtract(sets.kill_set); | ||
} | ||
builder.propagate_bits_into_graph_successors_of( | ||
in_out, &mut self.changed, (mir::BasicBlock::new(bb_idx), bb_data), dirty_queue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need the changed
flag anymore -- the only bit that matters is if the dirty queue is empty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed changed
flag.
src/librustc_mir/dataflow/mod.rs
Outdated
let entry_set = self.flow_state.sets.for_block(bb.index()).on_entry; | ||
let set_changed = bitwise(entry_set.words_mut(), | ||
in_out.words(), | ||
&self.flow_state.operator); | ||
if set_changed { | ||
*changed = true; | ||
for row in self.mir.basic_blocks()[*bb].terminator().successors(){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, bb
here is already the successor -- we just need to do
dirty_list.insert(*bb);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed!
src/librustc_mir/dataflow/mod.rs
Outdated
@@ -877,13 +885,18 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation | |||
fn propagate_bits_into_entry_set_for(&mut self, | |||
in_out: &IdxSet<D::Idx>, | |||
changed: &mut bool, | |||
bb: &mir::BasicBlock) { | |||
bb: &mir::BasicBlock, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pre-existing, but I think we should change the type of bb
here to bb: mir::BasicBlock
-- the &
is silly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed !
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks functionally correct! Exciting. I left some nits.
src/librustc_mir/dataflow/mod.rs
Outdated
propcx.changed = false; | ||
propcx.walk_cfg(&mut temp); | ||
} | ||
let mut dirty_queue: WorkQueue<mir::BasicBlock> = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: we should probably move the dirty_queue
creation into walk_cfg
; or else merge walk_cfg
and this method. But anyway, doesn't matter.
src/librustc_mir/dataflow/mod.rs
Outdated
builder.propagate_bits_into_graph_successors_of( | ||
in_out, &mut self.changed, (mir::BasicBlock::new(bb_idx), bb_data)); | ||
self.builder.propagate_bits_into_graph_successors_of( | ||
in_out, (mir::BasicBlock::new(bb.index()), bb_data), dirty_queue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: mir::BasicBlock::new(bb.index())
is just bb
=)
src/librustc_mir/dataflow/mod.rs
Outdated
mir::TerminatorKind::Goto { ref target } | | ||
mir::TerminatorKind::Assert { ref target, cleanup: None, .. } | | ||
mir::TerminatorKind::Yield { resume: ref target, drop: None, .. } | | ||
mir::TerminatorKind::Drop { ref target, location: _, unwind: None } | | ||
mir::TerminatorKind::DropAndReplace { | ||
ref target, value: _, location: _, unwind: None | ||
} => { | ||
self.propagate_bits_into_entry_set_for(in_out, changed, target); | ||
self.propagate_bits_into_entry_set_for(in_out, *target, dirty_list); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: instead of *target
here, we can remove the ref
from ref target
in the patterns above
src/librustc_mir/dataflow/mod.rs
Outdated
{ | ||
match bb_data.terminator().kind { | ||
mir::TerminatorKind::Return | | ||
mir::TerminatorKind::Resume | | ||
mir::TerminatorKind::Abort | | ||
mir::TerminatorKind::GeneratorDrop | | ||
mir::TerminatorKind::Unreachable => {} | ||
|
||
mir::TerminatorKind::Goto { ref target } | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: i.e., change this to target
not ref target
(see below)
src/librustc_mir/dataflow/mod.rs
Outdated
} | ||
mir::TerminatorKind::Assert { ref target, cleanup: Some(ref unwind), .. } | | ||
mir::TerminatorKind::Drop { ref target, location: _, unwind: Some(ref unwind) } | | ||
mir::TerminatorKind::DropAndReplace { | ||
ref target, value: _, location: _, unwind: Some(ref unwind) | ||
} => { | ||
self.propagate_bits_into_entry_set_for(in_out, changed, target); | ||
self.propagate_bits_into_entry_set_for(in_out, *target, dirty_list); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: same here...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(and all the other cases below)
@bors try Local perf runs suggested this was not a win. |
⌛ Trying commit 2a5c3c469680e333ec06845b725cd07aaf1fae45 with merge ddc3f99bad126b9f5755177d82f651d8f91d8683... |
☀️ Test successful - status-travis |
@Mark-Simulacrum can we schedule a perf run for this PR please ? :) |
Perf run is scheduled. |
OK, the perf results are quite interesting: It seems like my local measurement was correct but misleading -- clap-rs did get slower (by 2.5%) but lots of stuff is way faster! |
This is r=me but:
|
This comment has been minimized.
This comment has been minimized.
src/librustc_mir/dataflow/mod.rs
Outdated
debug_assert!(in_out.words().len() == sets.on_entry.words().len()); | ||
in_out.overwrite(sets.on_entry); | ||
IdxSet::clone_from(in_out, sets.on_entry); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be overwrite
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done!
@bors r+ |
📌 Commit 09df6a0 has been approved by |
introduce dirty list to dataflow @nikomatsakis my naive implementation never worked, So, I decided to implement using `work_queue` data structure. This PR also includes your commits from `nll-liveness-dirty-list` branch. Those commits should not visible once your branch is merged. r? @nikomatsakis
☀️ Test successful - status-appveyor, status-travis |
These are some pretty great performance wins for some crates even in the non-NLL case! 👍 |
@nikomatsakis my naive implementation never worked, So, I decided to implement using
work_queue
data structure. This PR also includes your commits fromnll-liveness-dirty-list
branch. Those commits should not visible once your branch is merged.r? @nikomatsakis